#include <iostream>
#include <functional>
#include <map>
#include <memory>

// Events类模板：用于管理观察者的注册、注销和通知
template <typename F>
class Events
{
public:
    Events() : current_id_(0) {}

    // 注册观察者，返回唯一标识符
    int Connect(F &&slot)
    {
        int id = current_id_++;
        observers_[id] = std::forward<F>(slot);
        return id;
    }

    // 注销观察者
    void Disconnect(int id)
    {
        observers_.erase(id);
    }

    // 通知所有观察者 //调用容器中的函数
    template <typename... Args>
    void Notify(Args &&...args)
    {
        for (const auto &observer : observers_)
        {
            observer.second(std::forward<Args>(args)...);
        }
    }

private:
    std::map<int, F> observers_; // 存储观察者的容器
    int current_id_;             // 用于生成唯一标识符
};

// 定义一个更复杂的测试类
class StockPrice
{
public:
    // 价格变化通知
    void updatePrice(double oldPrice, double newPrice)
    {
        std::cout << "股票价格从 " << oldPrice << " 变化到 " << newPrice << std::endl;
    }

    // 交易量变化通知
    void updateVolume(int volume)
    {
        std::cout << "交易量变化为: " << volume << std::endl;
    }
};

// 定义市场监控类
class MarketWatcher
{
public:
    void onPriceAlert(double oldPrice, double newPrice)
    {
        if (newPrice - oldPrice > 10.0)
        {
            std::cout << "警告: 价格剧烈上涨!" << std::endl;
        }
        else if (oldPrice - newPrice > 10.0)
        {
            std::cout << "警告: 价格剧烈下跌!" << std::endl;
        }
    }
};

int main()
{
    // 定义不同类型的事件
    Events<std::function<void(double, double)>> priceEvent;
    Events<std::function<void(int)>> volumeEvent;

    // 创建观察者对象
    StockPrice stockObserver;
    MarketWatcher marketWatcher;

    // 注册价格变化的观察者
    int priceObserver1 = priceEvent.Connect(
        std::bind(&StockPrice::updatePrice, &stockObserver,
                  std::placeholders::_1, std::placeholders::_2));

    int priceObserver2 = priceEvent.Connect(
        std::bind(&MarketWatcher::onPriceAlert, &marketWatcher,
                  std::placeholders::_1, std::placeholders::_2));

    // 注册成交量变化的观察者
    int volumeObserver = volumeEvent.Connect(
        std::bind(&StockPrice::updateVolume, &stockObserver,
                  std::placeholders::_1));

    // 添加一些Lambda观察者
    priceEvent.Connect([](double old_price, double new_price)
                       { std::cout << "Lambda观察者: 价格变化幅度为 "
                                   << (new_price - old_price) << std::endl; });

    volumeEvent.Connect([](int volume)
                        {
        if (volume > 10000) {
            std::cout << "Lambda观察者: 大额交易警告!" << std::endl;
        } });

    // 测试不同场景
    std::cout << "\n=== 测试场景1: 小幅价格变化 ===" << std::endl;
    priceEvent.Notify(100.0, 105.0);

    std::cout << "\n=== 测试场景2: 大幅价格变化 ===" << std::endl;
    priceEvent.Notify(100.0, 120.0);

    std::cout << "\n=== 测试场景3: 正常交易量 ===" << std::endl;
    volumeEvent.Notify(5000);

    std::cout << "\n=== 测试场景4: 大额交易量 ===" << std::endl;
    volumeEvent.Notify(15000);

    // 移除部分观察者
    priceEvent.Disconnect(priceObserver2);

    std::cout << "\n=== 测试场景5: 移除观察者后的价格变化 ===" << std::endl;
    priceEvent.Notify(120.0, 90.0);

    return 0;
}